﻿package {
	import Box2D.Dynamics.b2Body;
	
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.geom.Rectangle;	

	/**
	 * ...
	 * @author Georg Kamptner
	 */
	public class Player 
	{
		protected var _id:uint;
		protected var _name:String="Player";
		protected var _game:Game;
		protected var _bodies:Array;
		protected var _iterator:uint;
		protected var _actions:Array;
		protected var _area:Rectangle;
		protected var _towerheight:Number=0;
		protected var _towertopwidth:Number =0;
		
		
		public static const ACTION_ADD_BODY:String = "ACTION_ADD_BODY";
		public static const ACTION_MOVE_BODY:String = "ACTION_MOVE_BODY";
		
		
		// -- getter & setter ----------------------------------------------------------------------------------
		public function get name():String { return _name; }
		
		public function set name(value:String):void 
		{
			_name = value;
		}
		
		public function get id():uint { return _id; }
		
		public function get area():Rectangle { return _area; }
		public function get towerheight():Number{return _towerheight;}
		public function set towerheight(value:Number) : void{ _towerheight = value;}
		public function get towertopwidth():Number{return _towertopwidth;}
		public function set towertopwidth(value:Number) : void{ _towertopwidth = value;}
		
		// -- constructor --------------------------------------------------------------------------------------
		public function Player(id:uint, name:String, game:Game, area:Rectangle) 
		{
			_id = id;
			_name = name;
			_game = game;
			_bodies = new Array();
			_iterator = 0;
			_actions = new Array();
			_area = area;
			
		}
		
		
		// -- methods ------------------------------------------------------------------------------------------
		public function resetActions():void
		{
			_actions = new Array();
			trace("reset actions");
			if (_game.game_type == Game.GAME_TYPE_A)
			{
				_actions.push(ACTION_ADD_BODY);
				_actions.push(ACTION_ADD_BODY);
				_actions.push(ACTION_ADD_BODY);
			}
			else
			{
				_actions.push(ACTION_MOVE_BODY);
				_actions.push(ACTION_ADD_BODY);
				_actions.push(ACTION_ADD_BODY);
				_actions.push(ACTION_ADD_BODY);
				_actions.push(ACTION_ADD_BODY);
				_actions.push(ACTION_ADD_BODY);
			}
		}
		
		public function getActions():Array
		{
			return _actions;
		}
		
		public function getActionIcons():Array
		{
			var actions:Array = new Array();
			var i:int = 0;
			var l:int = _actions.length;
			for (; i<l; ++i)
			{
				actions.push( getActionIcon(_actions[i]) );
			}
			
			return actions;
		}
		
		private function getActionIcon(action:String):DisplayObject
		{
			var color:String = "";
			switch (_id) 
			{
				case 0:
					color = "Red";
					break;
				case 1:
					color = "Blue";
					break;
				default :
					color = "NoColor";
					break;
			}
			
			switch (action) 
			{
				case Player.ACTION_ADD_BODY:
					return new (_game.asset_loader.getDefinitionOf("AddBodyIcon" + color))() as Sprite;
					break;
				case Player.ACTION_MOVE_BODY:
					return new (_game.asset_loader.getDefinitionOf("MoveBodyIcon" + color))() as Sprite;
					break;
				default :
					return null;
					break;
			}
		}
		
		public function executAction():void
		{
			_actions.pop();
			_game.resetIconsList();
			if(_actions.length == 0){
				//_game.state.swapPlayers();
				_game.state.changeStateToDefault();
				_game.showSwapPlayerMsg();
			}
			else
				updateWorldState();
		}
		
		private function updateWorldState():void
		{
			switch (_actions[_actions.length - 1]) 
			{
				case ACTION_ADD_BODY:
					_game.changeStateToAddBody();
					break;
				case ACTION_MOVE_BODY:
					_game.changeStateToModifyBodies();
					break;
				default :
					break;
			}
		}
		
		public function addBody(body:b2Body):void
		{
			body.m_userData.player = this;
			_bodies.push(body);
		}
		
		public function removeBodyFromPlayer(body: IGameBody) : void
		{
			resetIterator();
			while (hasNext()) {
				if(next() == body.body)
				{	
					_bodies.splice(_iterator-1,1);
				}
			}
		}
		
		public function removeAllBodies():void
		{
			resetIterator();
			while (hasNext()) {
				next().m_userData.destroy();
			}
			
			// release bodies array for GC
			_bodies = new Array();
		}
		
		public function enableDragAndDrop():void
		{	
			resetIterator();
			while (hasNext()) {
				next().m_userData.enableDragAndDrop();
			}
		}
		
		public function disableDragAndDrop():void
		{
			resetIterator();
			while (hasNext()) {
				next().m_userData.disableDragAndDrop();
			}
		}
		
		public function hasNext():Boolean
		{
			return (_iterator + 1 <= _bodies.length);
		}
		
		public function next():b2Body
		{
			return _bodies[_iterator++];
		}
		
		public function resetIterator():void
		{
			_iterator = 0;
		}
		
		public function checkForWin(world:GameWorld, required_height:int):Boolean
		{
			var tower:Array = world.getHighestTowerOfPlayer(this);
			var top:b2Body = tower[tower.length - 1];
			
			// mark highest Tower of player
			resetAlpha();
			var b:b2Body;
			for each( b in tower)
			{
				if(b.m_userData is IGameBody){
					if (b == top){
						b.m_userData.alpha = 0.7;
						_towerheight = world.getVerticalDistanceToGroundInPixels(b,this);
						_towertopwidth = world.getHorizontalDistanceToLeftBorderInPixels(b,this);
					}
					else
						b.m_userData.alpha = 0.4;
				}
			}
			
			// check f player won
			if ( world.getVerticalDistanceToGroundInPixels(top,this) > required_height )
				return true;
			
			return false;
		}
		
		private function resetAlpha():void
		{
			resetIterator();
			while (hasNext()) {
				next().m_userData.alpha = 1.0;
			}
		}
		
		public function activate():void
		{
			resetAlpha();
			resetActions();
			
			updateWorldState();
		}
		
		public function deactivate():void
		{
		}
		
		public function reset():void
		{
			removeAllBodies();
			_towerheight = 0;
			_towertopwidth = 0;
		}
	}
	
}